package com.personal.common.util;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;

import org.apache.commons.lang.StringUtils;

/**
 * 日期工具类
 * 
 * @author yugc
 */
public class DateUtil {

	/**
	 * yyyy-MM-dd
	 */
	public static final String FORMAT1 = "yyyy-MM-dd";

	/**
	 * yyyy.MM.dd
	 */
	public static final String FORMAT2 = "yyyy.MM.dd";

	/**
	 * yyyy/MM/dd
	 */
	public static final String FORMAT3 = "yyyy/MM/dd";

	/**
	 * yyyy-MM-dd HH:mm
	 */
	public static final String FORMAT4 = "yyyy-MM-dd HH:mm";

	/**
	 * yyyy.MM.dd HH:mm
	 */
	public static final String FORMAT5 = "yyyy.MM.dd HH:mm";

	/**
	 * yyyy/MM/dd HH:mm
	 */
	public static final String FORMAT6 = "yyyy/MM/dd HH:mm";

	/**
	 * yyyy-MM-dd HH:mm:ss
	 */
	public static final String FORMAT7 = "yyyy-MM-dd HH:mm:ss";

	/**
	 * yyyy.MM.dd HH:mm:ss
	 */
	public static final String FORMAT8 = "yyyy.MM.dd HH:mm:ss";

	/**
	 * yyyy/MM/dd HH:mm:ss
	 */
	public static final String FORMAT9 = "yyyy/MM/dd HH:mm:ss";

	/**
	 * yyyy_MM_dd_HH_mm_ss
	 */
	public static final String FORMAT10 = "yyyy_MM_dd_HH_mm_ss";

	/**
	 * yy-MM-dd
	 */
	public static final String FORMAT11 = "yy-MM-dd";

	/**
	 * yyyyMMdd
	 */
	public static final String FORMAT12 = "yyyyMMdd";

	/**
	 * yyyyMMddHHmmss
	 */
	public static final String FORMAT13 = "yyyyMMddHHmmss";

	/**
	 * yyyyMM
	 */
	public static final String FORMAT14 = "yyyyMM";
	/**
	 * yyyyMMddHHmmssSSS
	 */
	public static final String FORMAT15 = "yyyyMMddHHmmssSSS";

	public static Date getCurrentDate() {

		return new Date(System.currentTimeMillis());
	}

	/**
	 * 返回当前日期或时间
	 * 
	 * @param format
	 * @return
	 */
	public static String getCurrentDate(String format) {

		if (StringUtils.isBlank(format)) {
			format = FORMAT1;
		}

		Date date = new Date();

		SimpleDateFormat formatter = new SimpleDateFormat(format);

		String currentTime = formatter.format(date);

		return currentTime;
	}

	/**
	 * 返回当前时间
	 * 
	 * @return
	 */
	public static String getCurrentTime() {

		String datetime = getCurrentDate(FORMAT7);
		String time = datetime.substring(datetime.indexOf(" ") + 1);

		return time;
	}

	/**
	 * 返回当前时间加随机数
	 * 
	 * @return
	 */
	public static String getCurrentDateTimeRandom() {

		String datetime = getCurrentDate(DateUtil.FORMAT10) + "_" + Math.random();

		return datetime;
	}

	/**
	 * 返回当前时间和日期
	 * 
	 * @return
	 */
	public static String getCurrentDateTimeString() {

		return getCurrentDate(DateUtil.FORMAT7);

	}

	/**
	 * 返回当前日期
	 * 
	 * @return
	 */
	public static Date getCurrentDateTime() {

		String datetime = getCurrentDate(FORMAT7);

		return parseStringToDate(datetime, "");
	}

	public static Timestamp getCurrentTimestamp() {

		String datetime = getCurrentDate(FORMAT7);

		return parseStringToTimestamp(datetime, "");
	}

	/**
	 * 日期转换为字符串
	 * 
	 * @param date
	 *            日期
	 * @param format
	 *            格式
	 * @return 返回字符型日期
	 */
	public static String parseDateToString(Date date, String format) {

		String result = "";
		DateFormat formatter = null;
		try {
			if (date != null) {
				if (StringUtils.isBlank(format)) {
					formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				} else {
					formatter = new SimpleDateFormat(format);
				}
				result = formatter.format(date);
			}
		} catch (Exception e) {
		}

		return result;
	}

	/**
	 * 时间1-时间2的毫秒
	 * 
	 * @param t1
	 * @param t2
	 * @return
	 */
	public static long between(Timestamp t1, Timestamp t2) {

		if ((t1 != null) && (t2 != null)) {
			return t1.getTime() - t2.getTime();
		}

		return 0;
	}

	/**
	 * 两个日期date1-date2相减，相差的天数
	 * 
	 * @param date1
	 *            日期
	 * @param date2
	 *            日期
	 * @return 返回相减后的日期
	 */
	public static int betweenTwoDates(Date date1, Date date2) {

		return (int) ((getMillis(date1) - getMillis(date2)) / (24 * 3600 * 1000));
	}

	/**
	 * 将字符串转换为日期
	 * 
	 * @param str
	 * @return
	 * @throws ParseException
	 */
	public static Date parseStringToDate(String str, String format) {

		DateFormat formatter = null;
		Date date = null;
		if (StringUtils.isNotBlank(str)) {

			if (StringUtils.isBlank(format)) {
				formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			} else {
				formatter = new SimpleDateFormat(format);
			}

			try {
				date = formatter.parse(str);
			} catch (ParseException e) {
				e.printStackTrace();
			}
		}

		return date;
	}

	/**
	 * 返回日期中的年份
	 * 
	 * @param date
	 *            日期
	 * @return 返回年份
	 */
	public static int getYear(Date date) {

		Calendar c = Calendar.getInstance();
		c.setTime(date);

		return c.get(Calendar.YEAR);
	}

	/**
	 * 返回日期中的月份
	 * 
	 * @param date
	 *            日期
	 * @return 返回月份
	 */
	public static int getMonth(Date date) {

		Calendar c = Calendar.getInstance();
		c.setTime(date);

		return c.get(Calendar.MONTH) + 1;
	}

	/**
	 * 返回日期中的日
	 * 
	 * @param date
	 *            日期
	 * @return 返回日
	 */
	public static int getDay(Date date) {

		Calendar c = Calendar.getInstance();
		c.setTime(date);

		return c.get(Calendar.DAY_OF_MONTH);
	}

	/**
	 * 返回日期中的小时
	 * 
	 * @param date
	 *            日期
	 * @return 返回小时
	 */
	public static int getHour(Date date) {

		Calendar c = Calendar.getInstance();
		c.setTime(date);

		return c.get(Calendar.HOUR_OF_DAY);
	}

	/**
	 * 返回日期中的分钟
	 * 
	 * @param date
	 *            日期
	 * @return 返回分钟
	 */
	public static int getMinute(Date date) {

		Calendar c = Calendar.getInstance();
		c.setTime(date);

		return c.get(Calendar.MINUTE);
	}

	/**
	 * 返回日期中的秒钟
	 * 
	 * @param date
	 *            日期
	 * @return 返回秒钟
	 */
	public static int getSecond(Date date) {

		Calendar c = Calendar.getInstance();
		c.setTime(date);

		return c.get(Calendar.SECOND);
	}

	/**
	 * 返回日期代表的毫秒
	 * 
	 * @param date
	 *            日期
	 * @return 返回毫秒
	 */
	public static long getMillis(Date date) {

		Calendar c = Calendar.getInstance();
		c.setTime(date);

		return c.getTimeInMillis();
	}

	/**
	 * 返回当前日期代表的毫秒
	 * 
	 * @return
	 */
	public static long getCurrentTimeMillis() {

		return System.currentTimeMillis();
	}

	/**
	 * 日期加天数,可以向前加，向后加
	 * 
	 * @param date
	 *            日期
	 * @param day
	 *            天数
	 * @return 返回相加后的日期
	 */
	public static Date addDay(Date date, int day) {

		Calendar c = Calendar.getInstance();
		c.setTimeInMillis(getMillis(date) + ((long) day) * 24 * 3600 * 1000);

		return c.getTime();
	}
	
	public static Date addHour(Date date, int hour) {
		Calendar c = Calendar.getInstance();
		c.setTimeInMillis(getMillis(date) + ((long) hour) * 3600 * 1000);
		return c.getTime();
	}

	/**
	 * 日期加秒数,可以向前加，向后加
	 * 
	 * @param date
	 *            日期
	 * @param second
	 *            秒数
	 * @return 返回相加后的日期
	 */
	public static Date addSecond(Date date, long second) {

		Calendar c = Calendar.getInstance();
		c.setTimeInMillis(getMillis(date) + second * 1000);

		return c.getTime();
	}

	/**
	 * 根据一个日期，返回是星期几
	 * 
	 * @param sdate
	 * @return
	 */
	public static String getWeekByDate(String sdate) {

		// 再转换为时间
		Date date = parseStringToDate(sdate, "");
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		int day = c.get(Calendar.DAY_OF_WEEK);
		// day中存的就是星期几了，其范围 1~7
		// 1=星期日 7=星期六，其他类推
		return day + "";
	}

	/**
	 * 日期为一年中的第几周
	 * 
	 * @return
	 */
	public static String getWeekNum(Date date) {

		Calendar c = Calendar.getInstance(Locale.CHINA);
		c.setTime(date);
		String week = Integer.toString(c.get(Calendar.WEEK_OF_YEAR));

		return week;

	}

	public static java.sql.Date parseUtilDateToSqlDate(Date date) {

		if (date != null) {
			return new java.sql.Date(date.getTime());
		} else {
			return null;
		}
	}

	public static java.sql.Date parseStringToSqlDate(String dateStr, String format) {

		Date date = null;
		if (StringUtils.isBlank(format)) {
			date = parseStringToDate(dateStr, "yyyy-MM-dd HH:mm:ss");
		} else {
			date = parseStringToDate(dateStr, format);
		}

		return parseUtilDateToSqlDate(date);
	}

	public static Timestamp parseUtilDateToTimestamp(Date date, String format) {

		return parseStringToTimestamp(parseDateToString(date, format), format);
	}

	public static Date parseTimestampToUtilDate(Timestamp date, String format) {

		return parseStringToDate(parseDateToString(date, format), format);
	}

	public static Timestamp parseStringToTimestamp(String dateStr, String format) {

		if (StringUtils.isBlank(dateStr)) {
			return null;
		}

		Date date = null;
		if (StringUtils.isBlank(format)) {
			date = parseStringToDate(dateStr, "yyyy-MM-dd HH:mm:ss");
		} else {
			date = parseStringToDate(dateStr, format);
		}

		if (date != null) {
			long t = date.getTime();
			return new Timestamp(t);
		} else {
			return null;
		}
	}

	/**
	 * 获取时间2099-12-31，23:59:59
	 * 
	 * @return
	 */
	public static Timestamp getMaxTimestamp() {

		return DateUtil.parseStringToTimestamp("2099-12-31 23:59:59", DateUtil.FORMAT7);
	}

	public static Date getMaxDate() {
		return parseStringToDate("2099-12-31 23:59:59", DateUtil.FORMAT7);
	}

	/**
	 * 返回日期中的年月日，格式化成yyyyMMdd
	 * 
	 * @param date
	 * @return
	 */
	public static String getYearMonthDay(Date date) {

		SimpleDateFormat formatter = new SimpleDateFormat(FORMAT12);

		String currentTime = formatter.format(date);

		return currentTime;
	}

	/**
	 * 返回日期中的年月日时分秒毫秒，格式化成yyyyMMddHHmmssSSS
	 * 
	 * @param date
	 * @return
	 */
	public static String getCurrentDateTimeSSS() {
		Date date = new Date();
		SimpleDateFormat formatter = new SimpleDateFormat(FORMAT15);

		String currentTime = formatter.format(date);

		return currentTime;
	}

	/**
	 * 取得指定月份的第一天
	 * 
	 * @param strdate
	 *            String
	 * @return String
	 */
	public static String getMonthBegin(String strdate) {

		return parseDateToString(parseStringToDate(strdate, "yyyy-MM"), "");
	}

	/**
	 * 取得指定月份的最后一天
	 * 
	 * @param strdate
	 *            String
	 * @return String
	 */
	public static String getMonthEnd(String strdate) {

		Date date = parseStringToDate(getMonthBegin(strdate), "");
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.MONTH, 1);
		calendar.add(Calendar.DAY_OF_YEAR, -1);

		return parseDateToString(calendar.getTime(), "");
	}

	public static String getPreviousMonthBegin() {

		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) - 1);
		Date date = new Date(cal.getTimeInMillis());

		return parseDateToString(parseStringToDate(parseDateToString(date, FORMAT1), "yyyy-MM"), FORMAT1);
	}

	public static String getPreviousMonthEnd() {

		Date date = parseStringToDate(getPreviousMonthBegin(), FORMAT1);
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.MONTH, 1);
		calendar.add(Calendar.DAY_OF_YEAR, -1);

		return parseDateToString(calendar.getTime(), FORMAT1);
	}

	/**
	 * 判断两个日期是否在同一周
	 * 
	 * @param date1
	 * @param date2
	 * @return
	 */
	public static boolean isSameWeekDates(Date date1, Date date2) {

		Calendar cal1 = Calendar.getInstance();
		Calendar cal2 = Calendar.getInstance();
		cal1.setTime(date1);
		cal2.setTime(date2);
		int subYear = cal1.get(Calendar.YEAR) - cal2.get(Calendar.YEAR);
		if (0 == subYear) {
			if (cal1.get(Calendar.WEEK_OF_YEAR) == cal2.get(Calendar.WEEK_OF_YEAR)) {
				return true;
			}
		} else if ((1 == subYear) && (11 == cal2.get(Calendar.MONTH))) {
			// 如果12月的最后一周横跨来年第一周的话则最后一周即算做来年的第一周
			if (cal1.get(Calendar.WEEK_OF_YEAR) == cal2.get(Calendar.WEEK_OF_YEAR)) {
				return true;
			}
		} else if ((-1 == subYear) && (11 == cal1.get(Calendar.MONTH))) {
			if (cal1.get(Calendar.WEEK_OF_YEAR) == cal2.get(Calendar.WEEK_OF_YEAR)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 得到每天的起始结束时间
	 * @description:TODO(简要描述此方法的作用)
	 * @author:     qimaoshen
	 * @date:       2015年5月23日 上午10:45:57
	 * @version:	v1.0 
	 * @return
	 * @return: 	Date[]
	 * @throws:
	 */
	public static Date[] getDayStartEndDate() {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date());
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);

		Date start = calendar.getTime();

		calendar.add(Calendar.DAY_OF_MONTH, 1);
		calendar.add(Calendar.SECOND, -1);

		Date end = calendar.getTime();

		// System.out.println(start);
		// System.out.println(end);

		/* other way */
		SimpleDateFormat formater = new SimpleDateFormat("yyyy/MM/dd");
		SimpleDateFormat formater2 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");

		try {
			start = formater2.parse(formater.format(new Date()) + " 00:00:00");
		} catch (ParseException e) {
			e.printStackTrace();
		}
		try {
			end = formater2.parse(formater.format(new Date()) + " 23:59:59");
		} catch (ParseException e) {
			e.printStackTrace();
		}

		// System.out.println(start);
		// System.out.println(end);
		return new Date[] { start, end };
	}

	/**
	 * 得到每月的起始结束时间
	 * @description:TODO(简要描述此方法的作用)
	 * @author:     qimaoshen
	 * @date:       2015年5月23日 上午10:46:10
	 * @version:	v1.0 
	 * @return
	 * @return: 	Date[]
	 * @throws:
	 */
	public static Date[] getMonthStartEndDate() {

		Calendar cal = Calendar.getInstance();
		SimpleDateFormat datef = new SimpleDateFormat("yyyy-MM-dd");
		// 当前月的最后一天
		cal.set(Calendar.DATE, 1);
		cal.roll(Calendar.DATE, -1);
		Date endTime = cal.getTime();
		String endTime1 = datef.format(endTime) + " 23:59:59";
		// 当前月的第一天
		cal.set(GregorianCalendar.DAY_OF_MONTH, 1);
		Date beginTime = cal.getTime();
		String beginTime1 = datef.format(beginTime) + " 00:00:00";
		// System.out.println(beginTime1);
		// System.out.println(endTime1);
		SimpleDateFormat formater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date start = null;
		Date end = null;
		try {
			start = formater.parse(beginTime1);
			end = formater.parse(endTime1);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		// System.out.println(start);
		// System.out.println(end);
		return new Date[] { start, end };

	}

	public static Date getStringToDate(String date) {
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat(FORMAT1);
		Date da = null;
		try {
			da = simpleDateFormat.parse(date);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return da;
	}

	public static Date getStringToHms(String date) {
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat(FORMAT7);
		Date da = null;
		try {
			da = simpleDateFormat.parse(date + " 23:59:59");
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return da;
	}

	public static String getStringToDate(Date date) {
		SimpleDateFormat formatter = new SimpleDateFormat(FORMAT1);
		String currentTime = formatter.format(date);
		return currentTime;
	}

	public static void main(String[] args) {
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date[] dates = DateUtil.getDayStartEndDate();
		Date stime = dates[0];
		Date etime = dates[1];
		
		System.out.println(formatter.format(stime));
		System.out.println(formatter.format(etime));
	}
	public static void main2(String[] args) {

		System.out.println(getPreviousMonthBegin());
		System.out.println(getPreviousMonthEnd());
		System.out.println(getYearMonthDay(new Date()));
		System.out.println(getYearMonthDay(parseStringToDate("2009-11-2 12:1:21", FORMAT7)));
		System.out.println("current time: " + getCurrentDateTime());
		System.out.println("addsecond: " + addSecond(getCurrentDateTime(), -1L));
		Date date = new Date();
		System.out.println("current date: " + date.toString());

		System.out.println("test parseDateToString: " + parseDateToString(date, ""));
		System.out.println("test parseStringToDate: " + parseStringToDate("1990-01-1 00:00:00", ""));

		System.out.println("test getYear: " + getYear(date));
		System.out.println("test getMonth: " + getMonth(date));
		System.out.println("test getDay: " + getDay(date));
		System.out.println("test getHour: " + getHour(date));
		System.out.println("test getMinute: " + getMinute(date));
		System.out.println("test getSecond: " + getSecond(date));
		System.out.println("test getMillis: " + getMillis(date));
		System.out.println("test addDate: " + addDay(date, 2));
		System.out.println("test betweenTwoDays: " + betweenTwoDates(date, parseStringToDate("2010-12-12", FORMAT1)));
		System.out.println("test getWeekNum: " + getWeekNum(addDay(date, -2)));
		System.out.println("test getWeekByDate: " + getWeekByDate(parseDateToString(date, "")));
		System.out.println("test getMonthBegin: " + getMonthBegin(parseDateToString(date, "")));
		System.out.println("test getMonthEnd: " + getMonthEnd(parseDateToString(date, "")));
		System.out.println("test isSameWeekDates: " + isSameWeekDates(date, addDay(date, -2)));

	}

	/**
	 * 
	 * @description:判断是否是同一天
	 * @author:     bear
	 * @date:       2015年12月30日 下午12:38:45
	 * @version:	v1.0 
	 * @param date1
	 * @param date2
	 * @return
	 * @return: 	boolean
	 * @throws:
	 */
	public static boolean isSameDay(Date date1, Date date2) {
		return org.apache.commons.lang.time.DateUtils.isSameDay(date1, date2);
	}

	/**
	 * 
	 * @description:判断是否是同一天
	 * @author:     bear
	 * @date:       2015年12月30日 下午12:38:45
	 * @version:	v1.0 
	 * @param date1
	 * @param date2
	 * @return
	 * @return: 	boolean
	 * @throws:
	 */
	@SuppressWarnings("deprecation")
	public static boolean isSameMonth(Date date1, Date date2) {
		if (date1.getMonth() == date2.getMonth()) {
			return true;
		} else {
			return false;
		}
	}

	public static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");

	public static String dateTransformBetweenTimeZone(Date sourceDate, DateFormat formatter, TimeZone sourceTimeZone,
			TimeZone targetTimeZone) {
		Long targetTime = sourceDate.getTime() - sourceTimeZone.getRawOffset() + targetTimeZone.getRawOffset();
		return DateUtil.getTime(new Date(targetTime), formatter);
	}

	public static String getTime(Date date, DateFormat formatter) {
		return formatter.format(date);
	}
	
	public static Date subDayFromNow(int interval)
	{
		Calendar c = Calendar.getInstance();
		c.add(Calendar.DAY_OF_MONTH,interval);
		return c.getTime();
	}
	
	public static Date setHourMineSecondOfDay(Date date2Change,int hour,int minute,int second)
	{
		Calendar c = Calendar.getInstance();
		c.setTime(date2Change);
		c.set(c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH), hour, minute, second);
		
		return c.getTime();
	}
	
	public static String setHourMineSecondOfDayStr(Date date2Change,int hour,int minute,int second)
	{
		Calendar c = Calendar.getInstance();
		c.setTime(date2Change);
		c.set(c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH), hour, minute, second);
		
		SimpleDateFormat formatter = new SimpleDateFormat(FORMAT7);
		
		return formatter.format(c.getTime());
	}
}
